<?php

/**
 * Базовая реализация контроллера.
 *
 */
abstract class Kernel_Controller_Tokened extends Kernel_Controller_Abstract
{
    /**
     * Возвращает описание компонента, который обработает действие, полученное
     * из запроса.
     *
     * @return  mixed
     */
    abstract protected function _getFilterToken();

    /**
     * Возвращает наименование класса компонента, который обработает запрошенное
     * действие.
     *
     * @param   string  $name
     * @return  string
     */
    abstract protected function _getFilterClassName($name);

    /**
     * Возвращает объект, отвечающий за обработку запрошенного действия.
     *
     * @return  Kernel_Filter
     */
    protected function _getFilter() {
        return $this->_construct($this->_getFilterToken());
    }

    /**
     * Создает объект фильтра из наименования класса и параметров.
     *
     * @param   Kernel_Token    $token
     * @return  Kernel_Filter_Interface
     */
    protected function _construct($token) {

        if (!is_object($token = Kernel_Token::wrap($token))) {
            $this->_abort('Filter not specified');
        }

        // приводим нотацию в соответствии с именованием классов
        $name = str_camelize($token->getName());

        // проверяем наименование компонента на отсутствие всяких левых символов
        // в целях безопасности. все нормальные имена должны проходить эту проверку
        if (!ctype_alnum($name)) {
            $this->_abort('Specified filter name "' . $name .'" is incorrect');
        }

        // определяем наименование класса компонента
        $class = $this->_getFilterClassName($name);

        // пытаемся загрузить определение класса в явном виде, т.к. __autoload()
        // не может генерировать исключения
        try {
            Zend_Loader::loadClass($class);
        } catch (Zend_Exception $e) {

            // если класс не загрузился, значит нет такой страницы
            $this->_abort($e->getMessage());
        }

        return $this->_create($class, $token->getParams());
    }

    /**
     * Создает объект фильтра из наименования класса и параметров.
     *
     * @param   string  $class
     * @param   array   $params
     * @return  Kernel_Filter_Interface
     */
    protected function _create($class, $params) {
        return new $class($params);
    }
}
